package controler;
import model.LevelEditorModel;

/**
 * @author Damien Mabin
 */
/* abstract */class A_UserCommand 
{
	public static var s_Model			: LevelEditorModel;
	public static var s_Controler		: LevelEditorControler;
	
	/* Damien : J'explique en francais la fonction de la variable m_Stackable car il est probable qu'il faille la changer, et son fonctionnement est un peu compliqué
	 * Elle sert a quoi ? Elle sert a dire si on peu agréer 2 action du meme type si l'utilisateur les enchaine.
	 * Un exemple ? Oui : si l'utilisateur drag une selection il enchaine plusieurs actions MoveSelectedSomething.
	 * Si dans ce cas on met stackable a false, si l'utilisateur fait undo il reviendra au dernier appel a MoveSelectedSomething , ie pour revenir a la position intiale il devrai faire plein d'undo.
	 * Si on met stackable a true, au premier undo il reviendra a l'origine de son drag and drop
	 */
	public var m_Stackable				: Bool;
	public var m_CanBeUndo				: Bool;
	
	private var m_PreviousModelState 	: A_State;
	private var m_NextModelState 		: A_State;
	private var m_AgregatedCommands		: Array<A_UserCommand>;

	private function new(_NextModelState:A_State)
	{
		if (Type.getClass(this) == A_UserCommand)
		{
			throw "A_UserCommand is an abstract class, no instantiation please";
		}
		
		m_Stackable = false;
		m_NextModelState = _NextModelState;
		m_AgregatedCommands = new Array<A_UserCommand>();
		if (m_NextModelState != null)
		{
			m_PreviousModelState = s_Controler.GetState();
		}
	}

	public function DoCommand() : Void
	{
		if (m_NextModelState != null)
		{
			s_Controler.SetState(m_NextModelState);
		}
		for (i in 0 ... m_AgregatedCommands.length)
		{
			m_AgregatedCommands[i].DoCommand();
		}
	}

	public function UndoCommand() : Void
	{
		for (i in 0 ... m_AgregatedCommands.length)
		{
			m_AgregatedCommands[m_AgregatedCommands.length-1-i].UndoCommand();
		}
		if (m_PreviousModelState != null)
		{
			s_Controler.SetState(m_PreviousModelState);
		}
	}
	
	public function AgregateUserCommand(f_Command : A_UserCommand):Void
	{
		m_AgregatedCommands.push(f_Command);
	}
	
}